[IA64] Add event injection logic
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Tue, 23 May 2006 14:34:48 +0000 (08:34 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Tue, 23 May 2006 14:34:48 +0000 (08:34 -0600)
Add event inject logic. Because up to this point there's no place
to register callback, this patch doesn't break existing working flow.

Signes-off-by Kevin Tian <kevin.tian@intel.com>

xen/arch/ia64/xen/process.c
xen/arch/ia64/xen/vcpu.c
xen/include/asm-ia64/event.h

index 53ce9b4908c7f4a78362f95ae34550ee078cc7fa..644890198844207f0bf516ed357b5e7f78a51980 100644 (file)
@@ -246,6 +246,40 @@ printf("*#*#*#* about to deliver early timer to domain %d!!!\n",v->domain->domai
        reflect_interruption(isr,regs,IA64_EXTINT_VECTOR);
 }
 
+void reflect_event(struct pt_regs *regs)
+{
+       unsigned long isr = regs->cr_ipsr & IA64_PSR_RI;
+       struct vcpu *v = current;
+
+       /* Sanity check */
+       if (is_idle_vcpu(v) || !user_mode(regs)) {
+               //printk("WARN: invocation to reflect_event in nested xen\n");
+               return;
+       }
+
+       if (!event_pending(v))
+               return;
+
+       if (!PSCB(v,interrupt_collection_enabled))
+               printf("psr.ic off, delivering event, ipsr=%lx,iip=%lx,isr=%lx,viip=0x%lx\n",
+                      regs->cr_ipsr, regs->cr_iip, isr, PSCB(v, iip));
+       PSCB(v,unat) = regs->ar_unat;  // not sure if this is really needed?
+       PSCB(v,precover_ifs) = regs->cr_ifs;
+       vcpu_bsw0(v);
+       PSCB(v,ipsr) = vcpu_get_ipsr_int_state(v,regs->cr_ipsr);
+       PSCB(v,isr) = isr;
+       PSCB(v,iip) = regs->cr_iip;
+       PSCB(v,ifs) = 0;
+       PSCB(v,incomplete_regframe) = 0;
+
+       regs->cr_iip = v->arch.event_callback_ip;
+       regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
+       regs->r31 = XSI_IPSR;
+
+       v->vcpu_info->evtchn_upcall_mask = 1;
+       PSCB(v,interrupt_collection_enabled) = 0;
+}
+
 // ONLY gets called from ia64_leave_kernel
 // ONLY call with interrupts disabled?? (else might miss one?)
 // NEVER successful if already reflecting a trap/fault because psr.i==0
@@ -255,7 +289,6 @@ void deliver_pending_interrupt(struct pt_regs *regs)
        struct vcpu *v = current;
        // FIXME: Will this work properly if doing an RFI???
        if (!is_idle_domain(d) && user_mode(regs)) {
-               //vcpu_poke_timer(v);
                if (vcpu_deliverable_interrupts(v))
                        reflect_extint(regs);
                else if (PSCB(v,pending_interruption))
index 48a9a0d77ae2d6423db2607df796de7fb11861a4..99a2aaaef2b609b11f4ec1ff42119a90728a7383 100644 (file)
@@ -649,16 +649,18 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
                printf("vcpu_pend_interrupt: bad vector\n");
                return;
        }
-    if ( VMX_DOMAIN(vcpu) ) {
-           set_bit(vector,VCPU(vcpu,irr));
-    } else
-    {
-       if (test_bit(vector,PSCBX(vcpu,irr))) {
-//printf("vcpu_pend_interrupt: overrun\n");
+
+       if (vcpu->arch.event_callback_ip) {
+               printf("Deprecated interface. Move to new event based solution\n");
+               return;
+       }
+               
+       if ( VMX_DOMAIN(vcpu) ) {
+               set_bit(vector,VCPU(vcpu,irr));
+       } else {
+               set_bit(vector,PSCBX(vcpu,irr));
+               PSCB(vcpu,pending_interruption) = 1;
        }
-       set_bit(vector,PSCBX(vcpu,irr));
-       PSCB(vcpu,pending_interruption) = 1;
-    }
 }
 
 #define        IA64_TPR_MMI    0x10000
@@ -674,6 +676,9 @@ UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
 {
        UINT64 *p, *r, bits, bitnum, mask, i, vector;
 
+       if (vcpu->arch.event_callback_ip)
+               return SPURIOUS_VECTOR;
+
        /* Always check pending event, since guest may just ack the
         * event injection without handle. Later guest may throw out
         * the event itself.
@@ -1151,7 +1156,16 @@ void vcpu_pend_timer(VCPU *vcpu)
                // don't deliver another
                return;
        }
-       vcpu_pend_interrupt(vcpu, itv);
+       if (vcpu->arch.event_callback_ip) {
+               /* A small window may occur when injecting vIRQ while related
+                * handler has not been registered. Don't fire in such case.
+                */
+               if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
+                       send_guest_vcpu_virq(vcpu, VIRQ_ITC);
+                       PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
+               }
+       } else
+               vcpu_pend_interrupt(vcpu, itv);
 }
 
 // returns true if ready to deliver a timer interrupt too early
index c1210fd2c0a4321461ce2862bf70c544bf7940f5..2a1d55cec5b4feccb39b3c19de8a276988ff185e 100644 (file)
@@ -28,8 +28,8 @@ static inline void evtchn_notify(struct vcpu *v)
     if ( running )
         smp_send_event_check_cpu(v->processor);
 
-    if(!VMX_DOMAIN(v))
-       vcpu_pend_interrupt(v, v->domain->shared_info->arch.evtchn_vector);
+    if(!VMX_DOMAIN(v) && !v->arch.event_callback_ip)
+        vcpu_pend_interrupt(v, v->domain->shared_info->arch.evtchn_vector);
 }
 
 /* Note: Bitwise operations result in fast code with no branches. */